package com.ohuang.util_h.replaceActivity;

import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;


/**
 * Created by Milk on 3/31/21.
 * * ∧＿∧
 * (`･ω･∥
 * 丶　つ０
 * しーＪ
 * 此处无Bug
 */
 class HCallbackProxy implements IInjectHook, Handler.Callback {
    public static final String TAG = "HCallbackStub";
    private Handler.Callback mOtherCallback;
    private final AtomicBoolean mBeing = new AtomicBoolean(false);

    private final List<HandleIntent> mHandleIntents = new ArrayList<HandleIntent>();


    public void addHandleIntent(HandleIntent handleIntent) {
        mHandleIntents.add(handleIntent);
    }


    private Handler.Callback getHCallback() {
        return BRHandler.get(getH()).mCallback();
    }

    private Handler getH() {
        return BRActivityThread.mH();
    }

    @Override
    public void injectHook() {
        mOtherCallback = getHCallback();
        if (mOtherCallback != null && (mOtherCallback == this || mOtherCallback.getClass().getName().equals(this.getClass().getName()))) {
            mOtherCallback = null;
        }
        BRHandler.get(getH())._set_mCallback(this);
    }

    @Override
    public boolean isBadEnv() {
        Handler.Callback hCallback = getHCallback();
        return hCallback != null && hCallback != this;
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (!mBeing.getAndSet(true)) {
            try {
                Log.d(TAG, "handleMessage: msg.what=" + msg.what);
                if (BuildCompat.isPie()) {
                    if ( BRActivityThreadH.EXECUTE_TRANSACTION(msg.what)) {
                        handleLaunchActivity(msg.obj);
                    }
                } else {
                    if ( BRActivityThreadH.LAUNCH_ACTIVITY(msg.what)) {
                        handleLaunchActivity(msg.obj);
                    }
                }
                if (mOtherCallback != null) {
                    return mOtherCallback.handleMessage(msg);
                }
                return false;
            } finally {
                mBeing.set(false);
            }
        }
        return false;
    }

    private Object getLaunchActivityItem(Object clientTransaction) {
        List<Object> mActivityCallbacks = BRClientTransaction.get(clientTransaction).mActivityCallbacks();
        if (mActivityCallbacks == null) {
            mActivityCallbacks = BRClientTransaction.get(clientTransaction).mTransactionItems();
        }
        if (mActivityCallbacks == null) {
            return null;
        }
        for (Object obj : mActivityCallbacks) {
            if ("android.app.servertransaction.LaunchActivityItem".equals(obj.getClass().getCanonicalName())) {
                return obj;
            }
        }
        return null;
    }

    private void handleLaunchActivity(Object client) {
        Log.e(TAG, "handleLaunchActivity: ");
        Object r;
        if (BuildCompat.isPie()) {
            // ClientTransaction
            r = getLaunchActivityItem(client);
        } else {
            // ActivityClientRecord
            r = client;
        }
        if (r == null) {
            Log.e(TAG, "handleLaunchActivity: r is null");
            return;
        }

        Intent intent;
        IBinder token;
        if (BuildCompat.isPie()) {
            intent = BRLaunchActivityItem.get(r).mIntent();
        } else {
            intent = BRActivityThreadActivityClientRecord.get(r).intent();
        }

        if (intent == null) {
            Log.e(TAG, "handleLaunchActivity: intent is null");
            return;
        }
        Log.e(TAG, "handleLaunchActivity: intent" + intent);
        for (HandleIntent mHandleIntent : mHandleIntents) {
            if (mHandleIntent.onIntent(intent)) {
                return;
            }
        }
    }


}
